<template>
	<!-- 
      此组件只解决单张图片上传
      1、添加图片上传时呈现出 loading 的一个状态
      2、添加在图片上传完成后，鼠标放在图片上呈现出 “图片预览”、“删除图片” 的效果
      3、自定义图片大小以及方形圆形图片
   -->
	<div class="l-upload" :class="round ? 'round' : ''">
		<!-- el-upload 组件 -->
		<el-upload
			class="avatar-uploader"
			:style="uploadStyle"
			:headers="headers"
			:action="action"
			:show-file-list="false"
			:on-success="handleAvatarSuccess"
			:before-upload="beforeAvatarUpload"
			:on-progress="handleAvatarProgress"
			v-loading="uploadLoading">
			<div class="avatar" v-if="modelValue" @click.stop>
				<el-image class="image" :src="modelValue" ref="imageRef" />
				<!-- 鼠标 hover 是图片上方遮罩层 -->
				<div class="el-upload-actions">
					<!-- 图片预览ICON -->
					<div class="item" @click="handlePictureCardPreview">
						<el-icon size="18" color="#fff">
							<ZoomIn />
						</el-icon>
					</div>
					<!-- 图片删除ICON -->
					<div class="item" @click="handleRemove">
						<el-icon size="18" color="#fff">
							<Delete />
						</el-icon>
					</div>
				</div>
			</div>
			<el-icon v-else class="avatar-uploader-icon">
				<Plus />
			</el-icon>
		</el-upload>
		<!-- 实现图片大图预览 -->
		<!-- 注意 ElImageViewer 组件必须要使用v-if判断 -->
		<ElImageViewer v-if="isImageView" :url-list="srcList" @close="imageClose"></ElImageViewer>
	</div>
</template>

<script setup lang="ts">
import { defineProps, reactive, ref, toRefs, defineEmits } from 'vue'
import { Plus, ZoomIn, Delete } from '@element-plus/icons-vue' // 引入 Element 中的图标
import { ElImageViewer } from 'element-plus' // 实现图片预览的组件,注意这是 element-plus 中的哦

// import { getDomainName } from '@/utils/index' // 获取 域名地址
import Cookies from 'js-cookie'

const props = defineProps({
	// 父组件 v-model 绑定的值
	modelValue: {
		type: String
	},
	// 图片上传时的地址
	action: {
		type: String,
		default: 'http://127.0.0.1:5173/image/upload'
	},
	// 定义 el-upload 组件的样式
	uploadStyle: {
		type: Object,
		default: {
			width: '200px',
			height: '200px'
		}
	},
	// 图片是否为圆形
	round: {
		type: Boolean,
		default: false
	}
})

const state = reactive({
	uploadLoading: false, // 图片文件大时 呈现出一个上传中的loading状态
	headers: {
		// el-upload 自定义 headers 头（根据自己的接口看是否需要）
		Authorization: Cookies.get('Token'),
		ContentType: 'application/json;charset=utf-8'
	},
	isImageView: false, // 图片预览时的状态
	srcList: [] as any // 图片预览列表（可以是多张）
})

const { headers, uploadLoading, isImageView, srcList } = toRefs(state)
const imageRef = ref()

const emit = defineEmits(['update:modelValue'])

// 预览图片
function handlePictureCardPreview() {
	state.isImageView = true
}

// 关闭图片预览
function imageClose() {
	state.isImageView = false
	state.srcList = [] // 每次关闭图片预览时清空一下
}

// 删除图片
function handleRemove() {
	emit('update:modelValue', '')
}

// 图片上传成功
function handleAvatarSuccess(response: any, file: any, fileList: any) {
	// response 上传成功返回的数据，根据自己的情况来写。
	// let url = getDomainName() + response.data.url
	let url = 'blob:http://127.0.0.1:5173/2c3f565d-9ec2-435c-9b14-042b272717a4'
	emit('update:modelValue', url)
	state.srcList.push(url)
	state.uploadLoading = false
}
// 图片上传之前
function beforeAvatarUpload() {}

// 图片上传时
function handleAvatarProgress() {
	state.uploadLoading = true
}
</script>

<style scoped lang="scss">
.l-upload {
	::v-deep .el-upload {
		width: 100%;
		height: 100%;
		border: 1px dashed #dcdfe6;
	}

	.avatar-uploader {
		.avatar {
			width: 100%;
			height: 100%;
			cursor: auto;
			position: relative;

			.image {
				width: 100%;
				height: 100%;
			}

			.el-upload-actions {
				top: 0;
				left: 0;
				cursor: auto;
				width: 100%;
				height: 100%;
				transition: 0.5s;
				position: absolute;
				background: rgba($color: #000000, $alpha: 0.5);
				opacity: 0;
				display: flex;
				align-items: center;
				justify-content: center;

				.item {
					width: 30px;
					height: 30px;
					display: flex;
					cursor: pointer;
					align-items: center;
					justify-content: center;
				}
			}

			&:hover {
				.el-upload-actions {
					opacity: 1;
					display: flex;
					align-items: center;
					justify-content: center;
				}
			}
		}
	}
}

.round {
	::v-deep .el-upload {
		border-radius: 50px;
		overflow: hidden;
	}
}
</style>
